#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include<cstring>
#include ".\logger.h"
#define random(a,b) (rand()%(b-a+1))+a
using namespace std;
bool cmp(int x,int y){//sort从大到小排序 
	return x>y;
}
string zimu(int x){//数字变字母 
	string m;
	if(x==3) m="3";
	if(x==4) m="4";
	if(x==5) m="5";
	if(x==6) m="6";
	if(x==7) m="7";
	if(x==8) m="8";
	if(x==9) m="9";
	if(x==10) m="10";
	if(x==11) m="J";
	if(x==12) m="Q";
	if(x==13) m="K";
	if(x==14) m="A";
	if(x==15) m="2";
	if(x==16) m="little_king";
	if(x==17) m="big_king";
	return m;
}
int shuzi(string x){//字母变数字 
	int m;
	if(x=="3") m=3;
	if(x=="4") m=4;
	if(x=="5") m=5;
	if(x=="6") m=6;
	if(x=="7") m=7;
	if(x=="8") m=8;
	if(x=="9") m=9;
	if(x=="10") m=10;
	if(x=="J") m=11;
	if(x=="Q") m=12;
	if(x=="K") m=13;
	if(x=="A") m=14;
	if(x=="2") m=15;
	if(x=="little_king") m=16;
	if(x=="big_king") m=17;
	return m;
}
int famer_panduan(int x,int famer[],int last[]){
	int j=114514,s=0;
	if(x==1){//单出判断 
		for(int i=3;i<=17;i++){
			if(last[i]!=0) j=i;
			if(famer[i]!=0&&i>j){
				return i;
			}			
		}
	}
	if(x==2){//双判断 
		for(int i=3;i<=17;i++){
			if(last[i]==2) j=i;
			if(famer[i]==2&&i>j) return i;
		}
	}
	if(x==3){//三带一判断 
		for(int i=3;i<=17;i++){
			if(last[i]==3) j=i;
			if(famer[i]==3&&i>j){
				for(int j=3;i<=17;i++){
					if(famer[i]>=1&&i!=j) return i;
				}
			} 
		}
	}
	if(x==4){//三带2判断 
		for(int i=3;i<=17;i++){
			if(last[i]==3) j=i;
			if(famer[i]==3&&i>j){
				for(int j=3;i<=17;i++){
					if(famer[i]>=2&&i!=j) return i;
				}
			} 
		}
	}
	int l=0,flag=0,k,l_f=0,k_f=3,num;//k是最小的数 //顺子长度 //num为3位数，百位是长度，个位是最小的数 
	if(x==6){//对子 
		for(int i=3;i<=15;i++){
			if(last[i]==2&&flag==0){
				flag=1;
				k=i;
				l++;
				continue;
			}
			if(last[i]==2){
				l++;
			}
		}
		flag=0;
		for(int i=3;i<=15;i++){
			if(famer[i]>=2&&flag==0){
		    	flag=1;
		    	k_f==i;
		    	l_f++;
		    	continue;
			}
			if(famer[i]>=2) l_f++;
			if(famer[i]==1){
				if(l_f==l&&k_f>k){
					num=l*100+k_f;//百位为长度，十位和个位是最小的对数 
					return num;
				}
				if(l_f>l){
					num=l_f*100+k_f;
					return num; 
				}
				l_f=0;
				k_f=0;
			}
		}
	}
	if(x==7){//顺子 
		for(int i=3;i<=17;i++){
			if(last[i]==1&&flag==0){
				flag=1;
				l++;
				k=i;
				continue;
			}if(last[i]==1){
				l++;
			}
		}
		flag=0;
		for(int i=3;i<=17;i++){
			if(famer[i]!=0&&flag==0){
				flag=1;
				l_f++;
				k_f=i;
				continue;
			}
			if(famer[i]!=0){
				l_f++;
			}
			if(famer[i]==0){
				if(l_f==l&&k_f>k){
					num=l_f*100+k_f;//百位为长度，十位和个位是最小的数 
					return num;
				}
				if(l_f>l){
					num=l_f*100+k_f;
					return num;
				}
				l_f=0;
				k_f=0;
			}
		}
	}
	if(x!=5&&x!=11){//判断是否可炸 
		for(int i=3;i<=17;i++){
			if(famer[i]==4){
				if(famer[i]>=2 && i!=j){
					i+=114514;
				//	cout<<"aaaaaa114aaaaa";
					return i;//返回值减去114514； 
				} 
			}
		}
	}
	if(x==5){//炸判断  放在最后
		for(int i=3;i<=17;i++){
			if(last[i]!=4) j=i;
			if(famer[i]==4&&i>j){
				if(famer[i]>=2&&i!=j) return i;
			} 
		}
	}
	return 0;     //飞机默认要不起，王炸要不起; 
}
int famer_chu(int x[]){//如果地主要不起，农民出牌; 
	int duizi=0,shunzi=0,r;
	//优先出大牌    农民默认不会出飞机，因为本游戏背景为20世纪中期，农民没见过飞机 
	for(int i=3;i<=17;i++){//对子判断 
		if(x[i]>=2){
			duizi++;
		}else{
			if(duizi==3){
				//return 0;
				i+=298; //与famer_panduan的返回值一致 百位是长度，个位是对子中最小的数 
				i+=60000; //万位放name(出的牌的类型 
				return i;
			}
			duizi=0;
		}
	}
	for(int i=3;i<=17;i++){//顺子判断 
		if(x[i]!=0){
			shunzi++;
		}else{
			if(shunzi==6){
			//	cout<<i-5<<" "<<i-4<<" "<<i-3<<" "<<i-2<<" "<<i-1<<" "<<i;
				i+=595;   //与famer_panduan的返回值一致，方便计算 
				i+=70000;
				return i;
			}
			shunzi=0;
		}
	}
	for(int i=3;i<=17;i++){//三带2判断 
		if(x[i]==3){
			for(int j=3;i<=17;i++){
				if(x[j]>=2&&j!=i){
					//cout<<i<<" "<<i<<" "<<i<<" "<<j<<" "<<j;
					i+=40000;
					return i;
				}
			}
		}
	}
	for(int i=3;i<=17;i++){//三带一判断 
		if(x[i]==3){
			for(int j=3;i<=17;i++){
				if(x[j]!=0&&j!=i){
					//cout<<i<<" "<<i<<" "<<i<<" "<<j;
					i+=30000;
					return i;
				}
			}
		}
	}
	for(int i=3;i<=17;i++){//双出判断 
		if(x[i]>=2){
			i+=20000;
			return i;
		}
	}
	for(int i=3;i<=17;i++){//单出判断 
		if(x[i]!=0){
			i+=10000;
			return i;
		}
	}
}
int panduan(string x[],int y,int n[]){
	int m[20],m1[20]={0},shun=1,dui=1;
	for(int i=0;i<y;i++){
		m[i]=shuzi(x[i]);
		m1[m[i]]++;
	} 
	for(int i=3;i<=17;i++){
		//cout<<m1[i]<<" ";
		if(m1[i]<=n[i]) continue;
		else return 0;
	}
	if(y==1) return 1;//单出 
	if(y==2&&m[1]==m[0]) return 2;//双 
	if(y==4 && m[0]==m[1]&&m[1]==m[2]&&m[0]!=m[3] /*&& m[0]!=m[3] &&*/ ) return 3;//三带一 
	if(y==5&&m[0]==m[1]&&m[1]==m[2]&&m[0]!=m[3]&&m[3]==m[4]) return 4;//三带二 
	if(y==4&&m[0]==m[1]&&m[1]==m[2]&&m[2]==m[3]) return 5;//炸; 
	if(y>=5){
		for(int i=1;i<y;i++){
			if(m[i-1]-m[i]==-1) continue;
			else shun=0;
		}
		for(int i=0;i<y;i+=2){
			if(m[i]==m[i+1]) continue;
			else dui=0;
		}
		if(shun==1) return 7;//顺子 
		if(dui==1) return 6;//对子 
	}
	//if (m[0]==m[1] && m[1]==m[2]) cout<<1;
	//if (m[3]==m[4] && m[4]==m[5]) cout<<2;
	if(m[0]==m[1] && m[1]==m[2] &&
	   m[3]==m[4] && m[4]==m[5]){
		if(y==8 && 
		   m[0]==m[1] && m[1]==m[2] & 
		   m[3]==m[4]&&m[4]==m[5] & 
		   m[6]!=m[7]) return 8;//两个三带单飞机 
		if(y==10 && 
		   m[0]==m[1]&&m[1]==m[2] &&
		   m[3]==m[4]&&m[4]==m[5] & 
		   m[6]==m[7] && 
		   m[8]==m[9]) return 9;//两个三带双飞机 		 
	}
	if(m[0]==17&&m[1]==16) return 11; //王炸; 
	return 0;
}
int dizhu_panduan(string dizhu[],int last[]){
	int l_d=0,l_l=0,i=0;
	while(dizhu[i]!="0"){
		l_d+=shuzi(dizhu[i]);
		i++;
	}
	i=0;
	while(last[i]){
		l_l+=last[i];
		i++;
	}
	if(l_d>l_l) return 1;//判断出的牌大小加起来有没有上一次出的牌大 
	else return 0;
}
int main(){
	using namespace logger;
	srand((int)time(0));
	string b[54]={"3","4","5","6","7","8","9","10","J","Q","K","A","2","3","4","5","6","7","8","9","10","J","Q","K","A","2","3","4","5","6","7","8","9","10","J","Q","K","A","2","3","4","5","6","7","8","9","10","J","Q","K","A","2","little_king","big_king"};
	string c[20],d[20],e[20],f[3];   //c，d，e分别为第一副，第二副，第三副  f地主牌 
	int mode,n,i=0,m=0,c1[20],d1[20],e1[20],c2[20]={0},d2[20]={0},e2[20]={0};//转换为数字的牌组; // c2,d2,e2为桶排序，判断出牌牌组中是否有; 
	cout<<"1:普通模式"<<endl<<"2:自定义"<<endl;
	cin>>mode;
	if(mode == 1){
		goto stop3;
	}
	if(mode == 2){
		goto stop4;
	}
	stop3:
	while(1){
		n=random(0,53);
		if(b[n]!="0"){
			c[i]=b[n];
			b[n]="0";
			i++;
		}
		if(i==17){
			i=0;
			break;
		}
	}
	while(1){
		n=random(0,53);
		if(b[n]!="0"){
			d[i]=b[n];
			b[n]="0";
			i++;
		}
		if(i==17){
			i=0;
			break;
		}
	}
	while(1){
		n=random(0,53);
		if(b[n]!="0"){
			e[i]=b[n];
			b[n]="0";
			i++;
		}
		if(i==17){
			i=0;
			break;
		}
	}
	i=0;
	cout<<"农民1:" ;
	for(int j=0;j<=16;j++){
		d1[j]=shuzi(d[j]);
	}
	stop4:
		if(mode == 2){
			string tmp_crd;
			int i=0;
			cout<<"输入农民1的牌:";
			while(1){
				cin>>tmp_crd;
				d1[i]=shuzi(tmp_crd);
				i++;
				for(int k=0;k<=54;i++){
					if(tmp_crd == b[k]){
						info("enter1");
						b[k] = "0";
						break;
					}
					/*else{
						cout<<"错误定义 ";
						break; 
					}*/
				} 
				if(i==17){
					break;
				}
			}
			i=0;
			cout<<"输入农民2的牌:";
			while(1){
				cin>>tmp_crd;
				e1[i]=shuzi(tmp_crd);
				i++;
				for(int k=0;k<=54;k++){
					if(tmp_crd==b[k]){
						info("enter2");
						b[k]="0";
						break;
					}
					/*else{
						cout<<"错误定义 ";
						break; 
					}*/
				}
				if(i==17){
					break;
				}
			}
		}
	sort(d1,d1+17,cmp);
	for(int j=0;j<=16;j++){
		d[j]=zimu(d1[j]);
		cout<<d[j]<<" ";
	}
	cout<<endl;
	cout<<"农民2:";
	for(int j=0;j<=16;j++){
		e1[j]=shuzi(e[j]);
	}
	sort(e1,e1+17,cmp);
	for(int j=0;j<=16;j++){
		e[j]=zimu(e1[j]);
		cout<<e[j]<<" ";
	}
	cout<<endl;
	cout<<"地主牌";//地主牌默认给玩家; 
	int j_dizhu=17;
	for(int j=0;j<=54;j++){
		if(b[j]!="0"){
			c[j_dizhu]=b[j];
			j_dizhu+=1;
			cout<<b[j]<<" ";
		}
	}
	cout<<endl;
	cout<<"玩家:";  //玩家牌组; 
	for(int j=0;j<=19;j++){
		c1[j]=shuzi(c[j]);
		c2[c1[j]]++;       //c牌组与e，d牌组不同，分开桶排 
	}
	sort(c1,c1+20,cmp);
	for(int j=0;j<=19;j++){
		c[j]=zimu(c1[j]);
		cout<<c[j]<<" ";
	}
	cout<<endl;
	for(int j=0;j<=16;j++){
		e2[e1[j]]++;
		d2[d1[j]]++;
	}  
	string k[20];//要出的牌组                         falg_f1判断农民1是否出牌，防止农民互打 
	int i_k=0,name,l_c=20,l_d=17,l_e=17,last[20]={0},flag=0,falg_f1=0;//剩余牌数  falg判断地主本轮是否要得起 
	cout<<"输入0结束出牌"<<endl;
	while(1){
		i_k=0;//给出牌的牌组长度清零 
		flag=0; 
		falg_f1=0;
		while(1){ //输入出牌; 
			cin>>k[i_k];
			if(i_k==0&&k[i_k]=="0"){//主动弃牌 
				cout<<"要不起"<<endl;
				flag=1;
				cout<<"剩余牌数:"<<l_c<<endl;
				for(int i=17;i>=3;i--){
					for(int j=0;j<c2[i];j++){
						cout<<zimu(i)<<" ";
					}
				}//看c2数组
				cout<<endl;
				break;
			} 
			if(k[i_k]=="0"){
				//cout<<i_k;
				if(panduan(k,i_k,c2)!=0&&dizhu_panduan(k,last)){
					cout<<"正确"<<endl;
					for(int i=0;i<=20;i++) last[i]=0;//将上一次出的牌清空 
					name=panduan(k,i_k,c2);
					for(int i=0;i<i_k;i++){
						last[shuzi(k[i])]++;//赋值给另一数组，判断后出的牌是否大于出的牌 
						c2[shuzi(k[i])]--;
					}
					for(int i=0;i<20;i++) k[i]="0";//将上一次出的牌清空
					l_c-=i_k;
					cout<<"剩余牌数:"<<l_c<<endl;
					for(int i=17;i>=3;i--){
						for(int j=0;j<c2[i];j++){
							cout<<zimu(i)<<" ";
						}
					}//看c2数组 
					cout<<endl;
					break;
				}
				else{
					cout<<"错误出牌"<<endl; 
					i_k=-1;
				}
			}
			i_k++;
		}
		cout<<endl;
		int i1=famer_panduan(name,d2,last);
		int i2=famer_panduan(name,e2,last);
		if(flag==1){//优先出快打完的农民的牌 
			if(l_d>l_e){
				i1=famer_chu(d2);
			//	cout<<"114514  "<<i1<<"  ";
				name=i1/10000;
				i1=i1%10000;
			//	cout<<name;
			//	cout<<endl<<"114514   "<<i1<<"   114514   "<<name<<endl;
			}
			if(l_d<=l_e){
				i2=famer_chu(e2);
			//	cout<<name;
			//	cout<<"114514  "<<i2<<"  ";
				name=i2/10000;
				i2=i2%10000;
			//	cout<<name<<"   "<<i2;
				i1==0; //使农民1不再出牌 
			}
		}
		if(i1!=0){
			falg_f1=1; 
			cout<<"农民1出牌:"; 
			for(int i=0;i<=20;i++) last[i]=0;//将上一次出的牌清空 
			if(i1>114514){//如果上次出牌不为炸弹，但农民可炸,单独判断 
				i1-=114514; 
				cout<<zimu(i1)<<" "<<zimu(i1)<<" "<<zimu(i1)<<" "<<zimu(i1)<<" ";
				d2[i1]-=4;
				for(int i=0;i<=3;i++) last[i]=i1;
				l_d-=4;
				goto stop1;
			}
			if(name==1){
				cout<<zimu(i1);//单出 
				d2[i1]--;
				l_d-=1;
				for(int i=0;i<=0;i++) last[i]=i1;
			}
			if(name==2){
				cout<<zimu(i1)<<" "<<zimu(i1);//双出 
				d2[i1]-=2;
				l_d-=2;
				for(int i=0;i<=1;i++) last[i]=i1;
			}
			if(name==3){
				cout<<zimu(i1)<<" "<<zimu(i1)<<" "<<zimu(i1);
				for(int i=0;i<=2;i++) last[i]=i1;
				d2[i1]-=3;//三带一 
				for(int i=3;i<=17;i++){
					if(d2[i]!=0&&i!=i1){//去除出了三张牌的 
						cout<<" "<<zimu(i);
						d2[i]--;
						last[3]=i;
						break;
					}
				}
				l_d-=4;
			}
			
			if(name==4){
				cout<<zimu(i1)<<" "<<zimu(i1)<<" "<<zimu(i1);
				for(int i=0;i<=2;i++) last[i]=i1;
				d2[i1]-=3;//三带二 
				for(int i=3;i<=17;i++){
					if(d2[i]>=2&&i!=i1){//去除出了三张牌的 
						cout<<" "<<zimu(i)<<" "<<zimu(i);
						last[3]=i;
						last[4]=i;
						d2[i]-=2;
						break;
					}
				}
				l_d-=5;
			}
			int l_dui,min,l_last=0;
			if(name==6){//对子 
				l_dui=i1/100;
				min=i1%100;
				for(int i=0;i<l_dui;i++){
					cout<<zimu(min)<<" "<<zimu(min)<<" ";
					d2[min]-=2;
					last[l_last]=min;
					last[l_last]=min;
					min++;
					l_last+=2;		
				}
				l_d-=l_dui*2;
			}
			if(name==7){//顺子 
				l_dui=i1/100;
				min=i1%100;
				for(int i=0;i<l_dui;i++){
					cout<<zimu(min)<<" ";
					d2[min]--;
					last[l_last]=min;
					l_last++;
					min++;
				}
				l_d-=l_dui;
			}
			if(name==5){// 炸
				cout<<zimu(i1)<<" "<<zimu(i1)<<" "<<zimu(i1)<<" "<<zimu(i1)<<" ";
				d2[i1]-=4;
				for(int i=0;i<=3;i++) last[i]=i1;
				l_d-=4;
			}
		}
		else{
			cout<<"农民1要不起";
		}
		stop1:
		cout<<endl<<"农民1牌组:";
		for(int i=17;i>=3;i--){
			for(int j=0;j<d2[i];j++){
				cout<<" "<<zimu(i);
			}
		}//农民1剩余牌
		cout<<endl<<" 农民1剩余牌数"<<l_d;
		//农民2 出牌判断 
		cout<<endl<<endl;
		if(falg_f1==1){
			cout<<endl<<"农民2牌组:";
			for(int i=17;i>=3;i--){
				for(int j=0;j<e2[i];j++){
					cout<<zimu(i)<<" ";
				}
			}//农民2剩余牌
			cout<<endl<<" 农民2剩余牌数："<<l_e<<endl;
			cout<<endl<<endl<<endl;
			continue;
		}
		if(i2!=0){
			for(int i=0;i<=20;i++) last[i]=0;//将上一次出的牌清空 
			cout<<"农民2出牌:"; 
			if(i2>114514){//如果上次出牌不为炸弹，但农民可炸,单独判断 
				i2-=114514;
				cout<<zimu(i2)<<" "<<zimu(i2)<<" "<<zimu(i2)<<" "<<zimu(i2)<<" ";
				e2[i2]-=4;
				for(int i=0;i<=3;i++) last[i]=i2;
				l_e-=4;
				goto stop2;
				//break;
			}
			if(name==1){
				cout<<zimu(i2);//单出 
				e2[i2]--;
				for(int i=0;i<=0;i++) last[i]=i2;
				l_e-=1;
			}
			if(name==2){
				cout<<zimu(i2)<<" "<<zimu(i2);//双
				e2[i2]-=2;
				for(int i=0;i<=1;i++) last[i]=i2;
				l_e-=2;
			}
			if(name==3){
				cout<<zimu(i2)<<" "<<zimu(i2)<<" "<<zimu(i2);
				for(int i=0;i<=2;i++) last[i]=i2;
				e2[i2]-=3;//三带一 
				for(int i=3;i<=17;i++){
					if(e2[i]!=0&&i!=i2){//去除出了三张牌的 
						cout<<" "<<zimu(i);
						e2[i]--;
						last[3]=i;
						break;
					}
				}
				l_e-=4;
			}
			if(name==4){
				cout<<zimu(i2)<<" "<<zimu(i2)<<" "<<zimu(i2);
				for(int i=0;i<=2;i++) last[i]=i2;
				e2[i2]-=3;//三带二 
				for(int i=3;i<=17;i++){
					if(e2[i]>=2&&i!=i2){//去除出了三张牌的 
						cout<<" "<<zimu(i)<<" "<<zimu(i);
						last[3]=i;
						last[4]=i;
						e2[i]-=2;
						break;
					}
				}
				l_e-=5;
			}
			int l_dui2,min2,l_last2=0;
			if(name==6){//对子 
				l_dui2=i2/100;
				min2=i2%100;
				for(int i=0;i<l_dui2;i++){
					cout<<zimu(min2)<<" "<<zimu(min2)<<" ";
					e2[min2]-=2;
					last[l_last2]=min2;
					last[l_last2]=min2;
					min2++;
					l_last2+=2;		
				}
				l_e-=l_dui2*2;
			}
			if(name==7){//顺子 
				l_dui2=i2/100;
				min2=i2%100;
				for(int i=0;i<l_dui2;i++){
					cout<<zimu(min2)<<" ";
					e2[min2]--;
					last[l_last2]=min2;
					l_last2++;
					min2++;
				}
				l_e-=l_dui2;
			}
			if(name==5){// 炸
				cout<<zimu(i2)<<" "<<zimu(i2)<<" "<<zimu(i2)<<" "<<zimu(i2)<<" ";
				for(int i=0;i<=3;i++) last[i]=i2;
				e2[i2]-=4;
				l_e-=4;
			}
			
		}
		else{
			cout<<"农民2要不起";
		}
		stop2:
		cout<<endl<<"农民2牌组:";
		for(int i=17;i>=3;i--){
			for(int j=0;j<e2[i];j++){
				cout<<zimu(i)<<" ";
			}
		}//农民2剩余牌
		cout<<endl<<" 农民2剩余牌数："<<l_e<<endl;
		if(l_c==0){
			while(1){
				cout<<"耶唉";
			}
		}
		if(l_d==0||l_e==0){
			while(1){
				cout<<"66";
			}	
		}
		cout<<endl<<endl<<endl;
	}
	return 0;
}